import 'package:flutter/material.dart';
import 'package:scroll_to_index/scroll_to_index.dart';
import 'dart:math' as math;

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home:
          // NotificationListenerContent()
          // ListViewControllerContent(),
          ScrollToPositionContent(),
    );
  }
}

// 使用NotificationListener监听滚动
class NotificationListenerContent extends StatefulWidget {
  @override
  _NotificationListenerContentState createState() =>
      _NotificationListenerContentState();
}

class _NotificationListenerContentState
    extends State<NotificationListenerContent> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('NotificationListener监听滚动'),
      ),
      body: NotificationListener(
        onNotification: (ScrollNotification notification) {
          print('监听滚动');
          if (notification is ScrollStartNotification) {
            print('开始滚动');
          } else if (notification is ScrollUpdateNotification) {
            print(
                '正在滚动,总滚动距离${notification.metrics.maxScrollExtent},当前滚动距离：${notification.metrics.pixels}');
          } else if (notification is ScrollEndNotification) {
            print('结束滚动');
          }
          // 多个Notification嵌套不冒泡
          return true;
        },
        child: ListView.builder(
          itemBuilder: (context, index) => Text('数据$index'),
          itemExtent: 30.0,
          itemCount: 100,
        ),
      ),
    );
  }
}

// 使用controller监听滚动,不能监听开始、结束滚动
class ListViewControllerContent extends StatefulWidget {
  @override
  _ListViewControllerContentState createState() =>
      _ListViewControllerContentState();
}

class _ListViewControllerContentState extends State<ListViewControllerContent> {
  // initialScrollOffset出事滚动偏移
  ScrollController _scrollController =
      ScrollController(initialScrollOffset: 40);

  // 是否显示按钮
  bool _isShowTop = false;

  @override
  void initState() {
    super.initState();
    // 添加监听方法
    _scrollController.addListener(() {
      if (_scrollController.offset < 30 && _isShowTop) {
        setState(() {
          _isShowTop = !_isShowTop;
        });
      } else if (_scrollController.offset >= 30 && !_isShowTop) {
        setState(() {
          _isShowTop = !_isShowTop;
        });
      }
    });
  }

  @override
  void dispose() {
    super.dispose();
    _scrollController.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('滚动事件监听'),
      ),
      floatingActionButton: _isShowTop
          ? FloatingActionButton(
              onPressed: (() {
                _scrollController.animateTo(0.0,
                    duration: Duration(milliseconds: 100),
                    curve: Curves.linear);
              }),
              child: Icon(Icons.keyboard_arrow_up),
            )
          : null,
      body: ListView.builder(
        itemBuilder: (context, index) => Text('数据$index'),
        itemExtent: 30.0,
        controller: _scrollController, // 滑动监听
        itemCount: 100,
      ),
      persistentFooterButtons: [
        TextButton(onPressed: () {}, child: Text('滑动到指定位置'))
      ],
    );
  }
}

// 滚动到指定index,官方未支持，需要使用第三方 scroll_to_index
class ScrollToPositionContent extends StatefulWidget {
  @override
  _ScrollToPositionContentState createState() =>
      _ScrollToPositionContentState();
}

class _ScrollToPositionContentState extends State<ScrollToPositionContent> {
  // initialScrollOffset出事滚动偏移
  AutoScrollController _scrollController;

  final random = math.Random();

  // ListView数据：位置、随机高度
  List<List<int>> randomList;

  final scrollDirection = Axis.vertical;

  @override
  void initState() {
    super.initState();

    _scrollController = AutoScrollController(
        viewportBoundaryGetter: () =>
            Rect.fromLTRB(0, 0, 0, MediaQuery.of(context).padding.bottom),
        axis: scrollDirection);

    randomList = List.generate(
        100, (index) => [index, (1000 * random.nextDouble()).toInt()]);
  }

  @override
  void dispose() {
    super.dispose();
    _scrollController.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('滚动到指定位置'),
      ),
      body: ListView(
        controller: _scrollController,
        scrollDirection: scrollDirection,
        children: randomList.map((e) {
          return Padding(
              padding: EdgeInsets.all(12),
              child: getRowItem(
                e[0],
                math.max(e[1].toDouble(), 50.0),
              ));
        }).toList(),
      ),
      persistentFooterButtons: [
        TextButton(
            onPressed: () async {
              await _scrollController.scrollToIndex(13,
                  preferPosition: AutoScrollPosition.begin);
              _scrollController.highlight(13);
            },
            child: Text('滑动13'))
      ],
    );
  }

  Widget getRowItem(int index, double height) {
    return AutoScrollTag(
        key: ValueKey(index),
        highlightColor: Colors.black.withOpacity(0.1),
        controller: _scrollController,
        index: index,
        child: Container(
          height: height,
          decoration: BoxDecoration(
            border: Border.all(color: Colors.lightBlue, width: 4),
            borderRadius: BorderRadius.circular(8),
          ),
          child: Text("index:$index,height:$height"),
        ));
  }
}
